﻿using System.Collections;
using System.Collections.Generic;

namespace UnityEngine
{
    public static class ResourcesUtil
    {
        /// <summary>
        /// 异步加载完毕委托
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="result"></param>
        public delegate void OnLoadAsyncFinishEventHandler<T>(T result) where T : Object;
        /// <summary>
        /// 启动协程委托
        /// </summary>
        /// <param name="e"></param>
        /// <returns></returns>
        public delegate Coroutine OnStartLoadEventHander(IEnumerator e);

        /// <summary>
        /// 获取或设置同时最大加载异步加载数量
        /// </summary>
        public static int MaxAsyncLoadCount { get; set; }
        /// <summary>
        /// 获取当前异步加载数量
        /// </summary>
        public static int CurrentAsyncLoadCount { get; private set; }

        private static Queue<System.Action> m_waitQueue;

        static ResourcesUtil()
        {
            MaxAsyncLoadCount = 5;
            m_waitQueue = new Queue<System.Action>();
        }

        /// <summary>
        /// 异步加载,如果同时加载数量达到上限,则进行排队
        /// </summary>
        /// <typeparam name="T">加载数据类型</typeparam>
        /// <param name="path">加载数据路径</param>
        /// <param name="startCoroutine">启动协程方法,因为异步加载需要依赖协程</param>
        /// <param name="callback">加载完毕回调</param>
        public static void LoadAsync<T>(string path, OnStartLoadEventHander startCoroutine, OnLoadAsyncFinishEventHandler<T> callback) where T : Object
        {
            System.Action a = () =>
            {
                ResourceRequest request = Resources.LoadAsync<T>(path);
                startCoroutine(StartLoad(request, callback));
            };
            m_waitQueue.Enqueue(a);
            if (CurrentAsyncLoadCount < MaxAsyncLoadCount)
            {
                m_waitQueue.Dequeue()();
            }
        }

        /// <summary>
        /// 启动加载
        /// </summary>
        /// <typeparam name="T">加载数据的类型</typeparam>
        /// <param name="request">请求</param>
        /// <param name="callback">加载完毕回调</param>
        /// <returns></returns>
        private static IEnumerator StartLoad<T>(ResourceRequest request, OnLoadAsyncFinishEventHandler<T> callback) where T : Object
        {
            CurrentAsyncLoadCount++;
            yield return request;
            CurrentAsyncLoadCount--;
            callback(request.asset as T);
            //加载完毕后检查是否要继续启动下一个
            if (m_waitQueue.Count > 0 && CurrentAsyncLoadCount < MaxAsyncLoadCount)
            {
                m_waitQueue.Dequeue()();
            }
        }
    }
}